package com.xc.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xc.mapper.WhShelfMapper;
import com.xc.pojo.*;
import com.xc.pojo.input.WhShelfInput;
import com.xc.pojo.input.WhShelfPageInput;
import com.xc.pojo.input.WhShelfUnitsInput;
import com.xc.pojo.output.ShelfOutput;
import com.xc.pojo.output.WhShelfOutput;
import com.xc.pojo.output.WhShelfUnitsOutput;
import com.xc.service.IWhAreaService;
import com.xc.service.IWhShelfService;
import com.xc.service.IWhShelfTypeService;
import com.xc.service.IWhShelfUnitsService;
import lombok.RequiredArgsConstructor;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * <p>
 * 架子表 服务实现类
 * </p>
 *
 * @author author
 * @since 2024-04-15
 */
@Service
@RequiredArgsConstructor
public class WhShelfServiceImpl extends ServiceImpl<WhShelfMapper, WhShelf> implements IWhShelfService {

    private final IWhAreaService areaService;

    private final IWhShelfTypeService shelfTypeService;

    private final IWhShelfUnitsService shelfUnitsService;

    /**
     * 查询全部
     *
     * @return
     */
    public List<WhShelfOutput> getAll() {

        //返回的集合
        List<WhShelfOutput> shelfOutputs = new ArrayList<>();

        //查询全部货架shelf
        List<WhShelf> shelves = list();

        //复制值给output
        shelfOutputs = BeanUtil.copyToList(shelves, WhShelfOutput.class);

        for (int i = 0; i < shelves.size(); i++) {
            //根据货架id查询所在库区
            QueryWrapper<WhArea> wrapper = new QueryWrapper<>();
            wrapper.lambda().eq(WhArea::getId, shelves.get(i).getAreaId())
            //todo 加一个del_flag。这里没那个枚举类
//                    .eq(WhArea::getDelFlag, 0)
            ;
            WhArea area = areaService.getOne(wrapper);

            //给对应的output赋值库区编码
            shelfOutputs.get(i).setAreaCode(area.getCode());

            //根据货架类型id，查询货架对象获取名称
            WhShelfType shelfType = shelfTypeService.getById(shelves.get(i).getType());
            shelfOutputs.get(i).setType(shelfType.getRows() + "*" + shelfType.getColumns());

            //设置output类型名称
            //shelfOutputs.get(i).setType(shelfType.getName());

            //根据货架id查询货架的列出库入库id
            QueryWrapper<WhShelfUnits> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda()
                    .eq(WhShelfUnits::getShelfId, shelves.get(i).getId())
            //todo 加一个del_flag，再加一个根据name做一个升序ASC排序
//                    .eq(WhShelfUnits::getDelFlag,0)
//                    .orderByAsc(WhShelfUnits::getName)
            ;
            //查询出当前货架的所有出库出库记录
            List<WhShelfUnits> shelfUnits = shelfUnitsService.list(queryWrapper);
            //遍历对象，提取出入库id，存入新集合
/*            List<Long> list = new ArrayList<>();
            for (WhShelfUnits shelfUnit : shelfUnits) {
                //Excel里字段，先写列出，再写列入
                list.add(shelfUnit.getUnloadPointId());
                list.add(shelfUnit.getLoadPointId());
            }*/
            List<Long> list = shelfUnits.stream().flatMap(su -> Stream.of(su.getUnloadPointId(), su.getLoadPointId())).toList();

            //集合赋值out对象
            shelfOutputs.get(i).setList(list);
        }

        return shelfOutputs;
    }

    /**
     * 写入excel
     */
    public void export() {
        //现有文件地址
        String file = "C:\\Users\\Administrator\\Desktop\\导出.xlsx";

        //要添加的数据
        List<WhShelfOutput> outputList = getAll();

        //打开现有文件
        FileInputStream inputStream = null;
        FileOutputStream fileOutputStream = null;
        try {
            inputStream = new FileInputStream(new File(file));

            //获取第二页
            Workbook workbook = new XSSFWorkbook(inputStream);
            Sheet sheet = workbook.getSheetAt(1);

            //获取最后一行索引。循环从0开始，默认是最后一行下一行，+1
            int lastRowNum = sheet.getLastRowNum() + 1;

            for (int i = 0; i < outputList.size(); i++) {
                //list每个元素为一行
                Row row = sheet.createRow(i + lastRowNum);

                //获取元素。具体对象不能获取元素个数，只能一个一个写了吧
                Cell cell = row.createCell(0);
                cell.setCellValue(outputList.get(i).getAreaCode());//库区编码
                Cell cell1 = row.createCell(1);
                cell1.setCellValue(outputList.get(i).getName());//货架名称
                Cell cell2 = row.createCell(2);
                cell2.setCellValue(outputList.get(i).getCode());//货架编码
                Cell cell3 = row.createCell(3);
                cell3.setCellValue(outputList.get(i).getType());//货架类型改 1*1

                //输出列出入口id
                for (int j = 0; j < outputList.get(i).getList().size(); j++) {
                    //想要持续输出列,先创建列，后给列赋值
                    row.createCell(4 + j).setCellValue(outputList.get(i).getList().get(j));
                }
            }

            fileOutputStream = new FileOutputStream(file);
            workbook.write(fileOutputStream);

            fileOutputStream.close();
            inputStream.close();
            workbook.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        System.out.println("数据导出成功");
    }

    /**
     * Excel导入MySQL——获取Excel数据
     */
    public List<WhShelfOutput> getExcel(MultipartFile file) {
        if (file.isEmpty()) {
            //todo 之后取消注释
//            throw new BusinessException("9999", "文件错误");
        }
        //文件接收的对象
        ArrayList<WhShelfOutput> shelfOutputs = new ArrayList<>();

        //现有文件地址
        //String file = "C:\\Users\\Administrator\\Desktop\\绵阳台沃导入表格 - 副本.xlsx";

        //打开现有文件
        //FileInputStream inputStream = null;

        try {
            //inputStream = new FileInputStream(new File(file));

            //获取第二页
            Workbook workbook = new XSSFWorkbook(file.getInputStream());
            Sheet sheet = workbook.getSheetAt(1);

            //遍历每行
            for (int i = 3; i <= sheet.getLastRowNum(); i++) {
                //返回的对象
                WhShelfOutput shelfOutput = new WhShelfOutput();

                //获取当前行
                Row row = sheet.getRow(i);
                //当前行为null、读取下一行
                if (row == null) {
                    continue;
                }

                //获取当前行单元格数量
                int lastCellNum = (int) row.getLastCellNum();

                //赋值
                shelfOutput.setAreaCode(row.getCell(0).getStringCellValue());
                shelfOutput.setName(row.getCell(1).getStringCellValue());
                shelfOutput.setCode(row.getCell(2).getStringCellValue());
                shelfOutput.setType(row.getCell(3).getStringCellValue());
                //获取出入库点位id。单元格数量-1即为最后一个索引，刚好小于当前值
                ArrayList<Long> list = new ArrayList<>();
                for (int j = 4; j < lastCellNum; j++) {
                    if (row.getCell(j) == null) {
                        break;
                    }
                    list.add((long) row.getCell(j).getNumericCellValue());
                }
                shelfOutput.setList(list);

                //对象放入集合
                shelfOutputs.add(shelfOutput);

                file.getInputStream().close();
                workbook.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        shelfOutputs.forEach(System.out::println);
        return shelfOutputs;
    }

    /**
     * Excel导入mysql——生成单个添加时的数据集合
     */
    @Override
    public void importExcel(MultipartFile file) {
        //获取从Excel中读取的数据
        List<WhShelfOutput> excel = getExcel(file);
        if (excel.size() == 0) {
            //todo 取消注释
//            throw new BusinessException("9999", "excel数据为空");
        }

        //最终的集合
        List<WhShelfInput> shelfInputs = new ArrayList<>();

        //赋值货架编码跟货架名字
        shelfInputs = excel.stream().map(c -> {
            WhShelfInput whShelfInput = new WhShelfInput();

            BeanUtils.copyProperties(c, whShelfInput);

            whShelfInput.setCode(c.getCode());
            whShelfInput.setName(c.getName());

            //查询库区id
            QueryWrapper<WhArea> wrapper = new QueryWrapper<>();
            //todo 添加del_flag,如果库区删除了怎么搞
            wrapper.lambda().eq(WhArea::getCode, c.getAreaCode());
            WhArea area = areaService.getOne(wrapper);
            //todo 取消注释
            if (area == null) {
//                throw new BusinessException("9999", "库区不存在");
            }
            whShelfInput.setAreaId(String.valueOf(area.getId()));

            //查询货架id
            //todo 添加del_flag
            WhShelfType shelfType = shelfTypeService.getOne(new QueryWrapper<WhShelfType>().lambda()
                    .eq(WhShelfType::getName, c.getType()));

            whShelfInput.setType(String.valueOf(shelfType.getId()));


            //shelfUnits
            List<WhShelfUnitsInput> shelfUnitsInputs = new ArrayList<>();
            //遍历赋值
            for (int i = 0, col = 1; i < c.getList().size(); i += 2, col++) {
                WhShelfUnitsInput shelfUnitsInput = new WhShelfUnitsInput();
                //设置out跟in的值
                shelfUnitsInput.setColumns(col);
                shelfUnitsInput.setUnloadPointId(String.valueOf(c.getList().get(i)));
                shelfUnitsInput.setLoadPointId(String.valueOf(c.getList().get(i + 1)));
                shelfUnitsInputs.add(shelfUnitsInput);
            }
            whShelfInput.setShelfUnits(shelfUnitsInputs);

            return whShelfInput;
        }).collect(Collectors.toList());

        shelfInputs.forEach(System.out::println);

    }

    @Override
    public List<ShelfOutput> getList(WhShelfPageInput pageInput) {
        Page<WhShelf> list = lambdaQuery()
                .eq(WhShelf::getDelFlag, 0)
                .eq(WhShelf::getStatus, 0)
                .eq(pageInput.getAreaId() != null, WhShelf::getAreaId, pageInput.getAreaId())
                .eq(pageInput.getCode() != null, WhShelf::getCode, pageInput.getCode())
                .eq(pageInput.getType() != null, WhShelf::getType, pageInput.getType())
                .eq(pageInput.getName() != null, WhShelf::getName, pageInput.getName())
                .page(Page.of(pageInput.getPageNumber(), pageInput.getPageSize()));
        if (list.getRecords().size() == 0) {
            return null;
        }
        // 获取货架的类型id集合——货架名称，货架规格
        List<Long> typeIds = list.getRecords().stream().map(WhShelf::getType).toList();
        List<WhShelfType> whShelfTypes = shelfTypeService.listByIds(typeIds);
        Map<Long, WhShelfType> shelfTypeMap = whShelfTypes.stream().collect(Collectors.toMap(WhShelfType::getId, o -> o));
        // 获取货架的库区id集合
        List<Long> areaIds = list.getRecords().stream().map(WhShelf::getAreaId).toList();
        List<WhArea> areas = areaService.listByIds(areaIds);
        Map<Long, WhArea> areaMap = areas.stream().collect(Collectors.toMap(WhArea::getId, o -> o));
        // 获取货架id集合
        List<Long> shelfIds = list.getRecords().stream().map(WhShelf::getId).toList();
        List<WhShelfUnits> shelfUnits = shelfUnitsService.listByIds(shelfIds);
        Map<Long, List<WhShelfUnits>> shelfUnitsMap = shelfUnits.stream().collect(Collectors.groupingBy(WhShelfUnits::getShelfId));

        List<ShelfOutput> shelfOuts = BeanUtil.copyToList(list.getRecords(), ShelfOutput.class);
        for (ShelfOutput shelfOutput : shelfOuts) {
            if (shelfTypeMap.containsKey(Long.valueOf(shelfOutput.getType()))) {
                shelfOutput.setTypeName(shelfTypeMap.get(Long.valueOf(shelfOutput.getType())).getName());
                //规格
                shelfOutput.setWhShelfType(shelfTypeMap.get(Long.valueOf(shelfOutput.getType())));
            }
            if (areaMap.containsKey(shelfOutput.getAreaId())) {
                shelfOutput.setAreaName(areaMap.get(shelfOutput.getAreaId()).getName());
            }
            if (shelfUnitsMap.containsKey(shelfOutput.getId())) {
                shelfOutput.setShelfUnits(BeanUtil.copyToList(shelfUnitsMap.get(shelfOutput.getId()), WhShelfUnitsOutput.class));
            }
        }

        // shelfOuts.forEach(System.out::println);
        return shelfOuts;
    }

    @Override
    public List<WhShelf> getEntryList(WhShelfPageInput pageInput) {
        return list(new QueryWrapper<WhShelf>().lambda()
                .eq(WhShelf::getDelFlag, 0)
                .eq(WhShelf::getStatus, 0)
                .eq(pageInput.getAreaId() != null, WhShelf::getAreaId, pageInput.getAreaId())
                .eq(pageInput.getCode() != null, WhShelf::getCode, pageInput.getCode())
                .eq(pageInput.getType() != null, WhShelf::getType, pageInput.getType())
                .eq(pageInput.getName() != null, WhShelf::getName, pageInput.getName()));
    }

    public static void main(String[] args) {
        List<WhShelfOutput> excel = new ArrayList<>();
        List<WhShelfInput> inputs = new ArrayList<>();
        WhShelfInput input = new WhShelfInput();
        WhShelfOutput whShelfOutput1 = new WhShelfOutput();
        whShelfOutput1.setList(List.of(1L, 1L, 2L, 2L));
        whShelfOutput1.setCode("test1");
        whShelfOutput1.setName("test1");
        whShelfOutput1.setType("货架1*1");
        whShelfOutput1.setAreaCode("aaaa");
        WhShelfOutput whShelfOutput2 = new WhShelfOutput();
        whShelfOutput2.setList(List.of(1L, 1L, 2L, 2L));
        whShelfOutput2.setCode("test2");
        whShelfOutput2.setName("test2");
        whShelfOutput2.setType("货架2*2");
        whShelfOutput2.setAreaCode("bbbb");
        excel.add(whShelfOutput1);
        excel.add(whShelfOutput2);

        // BeanUtil.copyToList()
        inputs = BeanUtil.copyToList(excel, WhShelfInput.class);
        inputs.forEach(System.out::println);

        // Collections.copy(destination, source)
        // Collections.copy(inputs,excel);

        // BeanUtils.copyProperties(source, target)
        /*BeanUtils.copyProperties(excel,WhShelfInput.class);
        inputs.forEach(System.out::println);*/

        // BeanUtils.copyProperties(source, class)
        // BeanUtils.copyProperties(excel);
        input = BeanUtil.copyProperties(whShelfOutput1, WhShelfInput.class);
        System.out.println(input);


/*        ArrayList<String> list = new ArrayList<>();
        list.add("apple");
        list.add("banana");
        list.add("orange");

        String[] array = list.toArray(new String[0]);
        for (String s : array) {
            System.out.println(s);
        }*/

/*        List<WhShelfUnits> shelfUnits = new ArrayList<>();
        WhShelfUnits shelfUnit1 = new WhShelfUnits();
        shelfUnit1.setName("shelfUnit1");
        shelfUnit1.setLoadPointId(2L);
        shelfUnit1.setUnloadPointId(1L);
        WhShelfUnits shelfUnit2 = new WhShelfUnits();
        shelfUnit2.setName("shelfUnit2");
        shelfUnit2.setLoadPointId(4L);
        shelfUnit2.setUnloadPointId(3L);
        WhShelfUnits shelfUnit3 = new WhShelfUnits();
        shelfUnit3.setName("shelfUnit3");
        shelfUnit3.setLoadPointId(6L);
        shelfUnit3.setUnloadPointId(5L);
        Collections.addAll(shelfUnits, shelfUnit1, shelfUnit2, shelfUnit3);

        List<Long> longs = shelfUnits.stream().flatMap(su -> Stream.of(su.getUnloadPointId(), su.getLoadPointId())).toList();

        longs.forEach(System.out::println);*/




        /*List<List<Integer>> nestedList = Arrays.asList(
                Arrays.asList(1, 2, 3),
                Arrays.asList(4, 5, 6),
                Arrays.asList(7, 8, 9)
        );

        List<Integer> mappedList = nestedList.stream()
                .map(list -> list.stream().map(i -> i * 2).collect(Collectors.toList()))
                .flatMap(List::stream)
                .collect(Collectors.toList());

        List<Integer> collect = nestedList.stream()
                .flatMap(List::stream)
                .collect(Collectors.toList());

        List<List<Integer>> list1 = nestedList.stream()
                .map(list -> list.stream().map(i -> {
                    i = i * 2;
                    return i;
                }).collect(Collectors.toList())).collect(Collectors.toList());

        Stream<List<Integer>> listStream = nestedList.stream()
                .map(list -> list.stream().map(i -> i * 2).collect(Collectors.toList()));



        System.out.println("Mapped list: " + collect);*/
    }
}
